<template>
  <div class="editor">
    <quill-editor
      v-model:content="content"
      ref="editorRef"
      contentType="html"
      @textChange="(e) => $emit('update:modelValue', content)"
      :options="options"
      :style="styles"
    />
  </div>
</template>

<script setup>
import { Quill, QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { uploadFile } from "./api.js";

const props = defineProps({
  /* 编辑器的内容 */
  modelValue: {
    type: String,
  },
  /* 高度 */
  height: {
    type: Number,
    default: null,
  },
  /* 最小高度 */
  minHeight: {
    type: Number,
    default: null,
  },
  /* 只读 */
  readOnly: {
    type: Boolean,
    default: false,
  },
});

const editorRef = ref();
// 上传图片
const imageHandler = () => {
  const input = document.createElement("input");
  input.setAttribute("type", "file");
  input.setAttribute("accept", "image/*");
  input.click();
  input.onchange = async () => {
    const file = input.files ? input.files[0] : null;
    if (file) {
      const formData = new FormData();
      formData.append("file", file);
      try {
        const res = await uploadFile(formData, "/base/upload");
        const quill = toRaw(editorRef.value).getQuill();
        if (quill) {
          const range = quill.getSelection(true);
          quill.insertEmbed(range.index, "image", res.data["data-show-file"]);
        }
      } catch (error) {
        alert("图片上传失败");
      }
    }
  };
};

const options = ref({
  theme: "snow",
  bounds: document.body,
  debug: "warn",
  modules: {
    // 工具栏配置
    toolbar: {
      // ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
      // ["blockquote", "code-block"], // 引用  代码块
      // [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
      // [{ indent: "-1" }, { indent: "+1" }], // 缩进
      // [{ size: ["small", false, "large", "huge"] }], // 字体大小
      // [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
      // [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
      // [{ align: [] }], // 对齐方式
      // ["clean"], // 清除文本格式
      // ["link", "image"], // 链接、图片、视频
      container: [
        ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
        [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
        [{ align: [] }], // 对齐方式
        [{ size: ["small", false, "large", "huge"] }], // 字体大小
        [{ font: [] }], // 字体种类
        [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
        [{ direction: "ltl" }], // 文本方向
        [{ direction: "rtl" }], // 文本方向
        [{ indent: "-1" }, { indent: "+1" }], // 缩进
        [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
        [{ script: "sub" }, { script: "super" }], // 上标/下标
        ["blockquote", "code-block"], // 引用  代码块
        ["clean"], // 清除文本格式
        ["link", "image"], // 链接、图片、视频
      ],
      handlers: {
        image: imageHandler, // 点击图片触发事件
      },
    },
    clipboard: {
      matchers: [
        [
          "img[src]",
          async (node, delta) => {
            const base64code = node.getAttribute("src");
            if (base64code && base64code.indexOf("data:image") === 0) {
              const parts = base64code.split(";base64,");
              const contentType = parts[0].split(":")[1];
              let strArr = contentType.split("/");
              const raw = window.atob(parts[1]);
              const rawLength = raw.length;
              const uInt8Array = new Uint8Array(rawLength);
              for (let i = 0; i < rawLength; ++i) {
                uInt8Array[i] = raw.charCodeAt(i);
              }
              const blob = new Blob([uInt8Array], { type: contentType });
              const newFilename = "remark" + "." + strArr[1];
              const file = new File([blob], newFilename, { type: contentType });
              let formData = new FormData();
              formData.append("file", file);
              try {
                const res = await uploadFile(formData, "/base/upload");
                console.log("Upload response:", res); // 添加调试信息
                const quill = toRaw(editorRef.value).getQuill();
                if (quill) {
                  const range = quill.getSelection(true);
                  console.log("Quill instance and range:", quill, range); // 添加调试信息
                  if (range) {
                    quill.insertEmbed(range.index, "image", res.data["data-show-file"]);
                  } else {
                    console.error("No selection range found"); // 添加调试信息
                  }
                } else {
                  console.error("Quill instance not found"); // 添加调试信息
                }
              } catch (error) {
                alert("图片上传失败");
                return delta;
              }
            }
            return delta;
          },
        ],
      ],
    },
  },
  placeholder: "请输入内容",
  readOnly: props.readOnly,
  theme: "snow",
});

const styles = computed(() => {
  let style = {};
  if (props.minHeight) {
    style.minHeight = `${props.minHeight}px`;
  }
  if (props.height) {
    style.height = `${props.height}px`;
  }
  return style;
});

const content = ref("");
watch(
  () => props.modelValue || "",
  (v) => {
    if (v !== content.value) {
      content.value = v === undefined ? "" : v;
    }
  },
  { immediate: true }
);

// 将 data URL 转换为 Blob
const dataURLtoBlob = (dataurl) => {
  const arr = dataurl.split(",");
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
};
</script>

<style>
.editor,
.ql-toolbar {
  width: 100%;
  white-space: pre-wrap !important;
  line-height: normal !important;
}
.quill-img {
  display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: "保存";
  padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode="video"]::before {
  content: "请输入视频地址:";
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  content: "32px";
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "标题6";
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "等宽字体";
}
</style>
